from fastapi.encoders import jsonable_encoder
from sqlalchemy import func
from sqlalchemy.orm import Session
from passlib.apps import custom_app_context as pwd_context
from datetime import datetime, timedelta
import jwt
from common import models, schemas, logger
from common.database import SessionLocal
from conf.settings import *
from common.log_to_sql import get_logger

log = logger.tlog()
tlogger = log.define()

# to get a string like this run:
# openssl rand -hex 32
# SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
# ALGORITHM = "HS256"
# ACCESS_TOKEN_EXPIRE_MINUTES = 30
log_sql = get_logger()


# 获取当前用户
def get_user_by_username(db: Session, username: str):
    return db.query(models.Users).filter(models.Users.username == username).first()


def get_user_by_nickname(db: Session, nickname: str):
    return db.query(models.Users).filter(models.Users.nickname == nickname).first()


#########################################################################################################################################################
# 创建用户初始化权限
# 
#########################################################################################################################################################
def add_serpermission(db: Session, user: str, user_uuid: str):
    # fake_hashed_password = user.password + "notreallyhashed"
    userpermission = schemas.UserPermission
    userpermission.username = user
    userpermission.is_active = 1
    userpermission.user_uuid = user_uuid
    userpermission.scopesname = 'search'
    userpermission.path = '/search'
    userpermission.description = 'search company'
    userpermission.scopesgroup = 'report'
    create_userpermission(db=db, userpermission=userpermission)
    userpermission.scopesname = 'report_base'
    userpermission.path = '/report/base'
    userpermission.description = 'Report Base'
    userpermission.scopesgroup = 'report'
    create_userpermission(db=db, userpermission=userpermission)
    userpermission.scopesname = 'report_group'
    userpermission.path = '/report/group'
    userpermission.description = 'Report Group'
    userpermission.scopesgroup = 'report'
    create_userpermission(db=db, userpermission=userpermission)
    userpermission.scopesname = 'read_user'
    userpermission.path = '/user/var'
    userpermission.description = 'Report Group'
    userpermission.scopesgroup = 'User'
    create_userpermission(db=db, userpermission=userpermission)
    userpermission.scopesname = 'read_users'
    userpermission.path = '/users'
    userpermission.description = 'Report Group'
    userpermission.scopesgroup = 'User'
    create_userpermission(db=db, userpermission=userpermission)
    userpermission.scopesname = 'user_premission'
    userpermission.path = '/user/permission'
    userpermission.description = 'Report Group'
    userpermission.scopesgroup = 'User'
    create_userpermission(db=db, userpermission=userpermission)

    return True


#########################################################################################################################################################
# 创建用户 
# 
#########################################################################################################################################################
def create_user(db: Session, user: schemas.User):
    # fake_hashed_password = user.password + "notreallyhashed"
    fake_hashed_password = pwd_context.encrypt(user.password)
    db_user = models.Users(username=user.username, email=user.email, nickname=user.nickname, remark=user.password,
                           password_hash=fake_hashed_password, full_name=user.full_name, is_active=user.is_active)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    # log_sql.info("create user:" + db_user.username)
    tlogger.info("create user:" + db_user.username)
    add_serpermission(db=db, user=db_user.username, user_uuid=db_user.uuid)  # 添加初始化权限

    return db_user


#########################################################################################################################################################
# 获取所有用户
#########################################################################################################################################################
def get_users(db: Session, skip: int = 0, limit: int = 100):
    return db.query(models.Users).offset(skip).limit(limit).all()


def get_user(db: Session, username: str):
    return db.query(models.Users).filter(models.Users.username == username).first()


## 认证
def authenticate_user(db: Session, username: str, password: str):
    user = get_user(db, username)
    if not user:
        return False
    # tlogger.debug(password)
    if not verify_password(password, user.password_hash):
        return False
    return user


def verify_password(plain_password, hashed_password):
    # tlogger.debug(pwd_context.verify(plain_password, hashed_password))
    return pwd_context.verify(plain_password, hashed_password)


def create_access_token(*, data: dict, expires_delta: timedelta = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt.decode()


def authenticate_token(db: Session, plain_password, hashed_password):
    # tlogger.debug(pwd_context.verify(plain_password, hashed_password))
    return pwd_context.verify(plain_password, hashed_password)


def get_scope(db: Session, username: str):
    if not username:
        return []
    # user = db.query(models.UserPermission).filter(models.UserPermission.username == username).all()
    user = db.query(models.UserPermission.scopesname).filter(models.UserPermission.username == username,
                                                             models.UserPermission.is_active == 1).all()
    result = [dict(zip(result.keys(), result)) for result in user]
    return result


#########################################################################################################################################################
# 添加API权限
#########################################################################################################################################################
def create_userpermission(db: Session, userpermission: schemas.UserPermission):
    # fake_hashed_password = user.password + "notreallyhashed"
    # fake_hashed_password = pwd_context.encrypt(user.password)
    db_user = models.UserPermission(username=userpermission.username, scopesname=userpermission.scopesname,
                                    path=userpermission.path, description=userpermission.description,
                                    is_active=userpermission.is_active, user_uuid=userpermission.user_uuid,
                                    scopesgroup=userpermission.scopesgroup)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    tlogger.info("create user Permission: " + db_user.username + "path: " + userpermission.path)
    return db_user


#########################################################################################################################################################
# 用户申请API权限
#########################################################################################################################################################
def create_user_api_apply(db: Session, UserApiKey: schemas.UserApiKey, username, path):
    # fake_hashed_password = user.password + "notreallyhashed"
    # fake_hashed_password = pwd_context.encrypt(user.password)
    # 将数据存进数据库
    apply_name, apply_image, description = db.query(models.APISource.apply_name, models.APISource.api_image,
                                                    models.APISource.description).filter(
        models.APISource.aid == UserApiKey.apply_id).first()

    db_user = models.ApiKeyList(username=username, description=description, apply_name=apply_name,
                                apply_image=apply_image, path=path, apply_id=UserApiKey.apply_id,
                                is_active=UserApiKey.is_active)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    tlogger.info("create user Permission: " + db_user.username + "path: " + path)
    return db_user


#########################################################################################################################################################
# 用户已申请API权限
#########################################################################################################################################################
def query_user_one_api_apply(db: Session, UserApiKey: schemas.UserApiKey, username):
    # fake_hashed_password = user.password + "notreallyhashed"
    # fake_hashed_password = pwd_context.encrypt(user.password)
    # db_user = models.ApiKeyList(username=UserApiKey.username,scopesname=UserApiKey.scopesname,path=UserApiKey.path,\
    #    description=UserApiKey.description,is_active=UserApiKey.is_active,user_uuid=UserApiKey.user_uuid,scopesgroup=UserApiKey.scopesgroup)
    check_apply_id = db.query(models.APISource).filter(models.APISource.aid == UserApiKey.apply_id).first()
    if not check_apply_id:
        return 2
    db_user = db.query(models.ApiKeyList).filter(models.ApiKeyList.username == username,
                                                 models.ApiKeyList.apply_id == UserApiKey.apply_id).first()
    return db_user


#########################################################################################################################################################
# 用户已申请所有API权限
#
#########################################################################################################################################################
def query_user_all_api_apply(db: Session, UserApiKey: schemas.UserApiKey, username, page, limit):
    # fake_hashed_password = user.password + "notreallyhashed"
    # fake_hashed_password = pwd_context.encrypt(user.password)
    # db_user = models.ApiKeyList(username=UserApiKey.username,scopesname=UserApiKey.scopesname,path=UserApiKey.path,\
    #    description=UserApiKey.description,is_active=UserApiKey.is_active,user_uuid=UserApiKey.user_uuid,scopesgroup=UserApiKey.scopesgroup)
    db_user = db.query(models.ApiKeyList).filter(models.ApiKeyList.username == username).limit(limit).offset(
        (page - 1) * limit).all()
    count = db.query(models.ApiKeyList).filter(models.ApiKeyList.username == username).count()
    json_data = jsonable_encoder(db_user)
    result = {}
    result['total'] = count
    result['data'] = json_data
    return result


#########################################################################################################################################################
# 更改用户信息
#########################################################################################################################################################
def change_user(db: Session, user: schemas.User):
    # fake_hashed_password = user.password + "notreallyhashed"
    # fake_hashed_password = pwd_context.encrypt(user.password)
    data = db.query(models.Users).filter(models.Users.username == user.username).first()
    # data.password_hash = fake_hashed_password
    # data.remark = user.password
    if user.gender == '男':
        data.gender = '1'
    elif user.gender == '女':
        data.gender = '2'
    else:
        data.gender = '0'
    if user.nickname:
        data.nickname = user.nickname
    if user.email:
        data.email = user.email
    if user.full_name:
        data.full_name = user.full_name
    if user.is_active:
        data.is_active = user.is_active
    # 头像
    if user.head_sculpture:
        data.head_sculpture = user.head_sculpture
    # 生日
    data.birthday = user.birthday
    # 邮箱
    if user.email:
        data.email = user.email
    # 个人简介
    if user.profile:
        data.profile = user.profile
    # 职业
    if user.occupation:
        data.occupation = user.occupation
    # 公司
    if user.company:
        data.company = user.company
    # 公司地址
    if user.company_address:
        data.company_address = user.company_address
    # 技术标签
    if user.tech_label:
        data.tech_label = user.tech_label
    # 兴趣标签
    if user.hobby_tag:
        data.hobby_tag = user.hobby_tag
    # 联系地址
    if user.contact_address:
        data.contact_address = user.contact_address
    # 手机号
    if user.phone:
        data.phone = user.phone
    db.commit()
    tlogger.info("Change user:" + user.username)

    return user


#########################################################################################################################################################
# 更改密码
#########################################################################################################################################################
def change_user_passwd(db: Session, user: schemas.User):
    # fake_hashed_password = user.password + "notreallyhashed"
    try:
        fake_hashed_password = pwd_context.encrypt(user.password)
        data = db.query(models.Users).filter(models.Users.username == user.username).first()
        data.password_hash = fake_hashed_password
        data.remark = user.password
        db.commit()
        tlogger.info("Change user:" + user.username)
    except Exception as e:
        tlogger.warning(e)
    else:
        return user


#########################################################################################################################################################
# 更改登陆时间
#########################################################################################################################################################
def change_logintime(db: Session, user: str):
    data = db.query(models.Users).filter(models.Users.username == user).first()
    data.last_login_time = datetime.now()
    db.commit()
    return True


#########################################################################################################################################################
#########################################################################################################################################################


#########################################################################################################################################################
# 查询API清单
#########################################################################################################################################################
def query_api_list(db: Session, cid: str, page: int, limit: int):
    # cursor = db.execute(
    #     'select uuid,description,url,is_active from userbase.api_source where cid = :cid',
    #     params={"cid": cid})
    if cid:
        datas = db.query(models.APISource).filter(models.APISource.cid == cid).limit(limit).offset(
            (page - 1) * limit).all()
        count = db.query(models.APISource).filter(models.APISource.cid == cid).count()
        # tlogger.info(datas)
        result = {}
        result['total'] = count
        result['data'] = [jsonable_encoder(data) for data in datas]
    else:
        # 分组查询并返回前10条
        datas = db.query(func.concat_ws(',', models.APISource.cid, models.APISource.cate_name)).group_by(
            models.APISource.cid).all()
        tmp_datas = [jsonable_encoder(data) for data in datas]
        result = [{'cid': data[0].split(',')[0], "cate_name": data[0].split(',')[1]} for data in tmp_datas]
    # cursor = db.execute('select bid, company_name from tht.contact_information where bid =:bid', params={"bid": 'CN9360812942'})
    # 转换字典
    # result = [dict(zip(result.keys(), result)) for result in res_rows]
    # 将查询的分类全部返回
    return result
